package com.xb.cloud.order.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import com.xb.cloud.common.client.bo.UpdateInfo;
import com.xb.cloud.common.constant.DbConstants;
import com.xb.cloud.common.util.BeanUtils;
import com.xb.cloud.order.model.HistorySo;
import com.xb.cloud.order.model.ProductStock;
import com.xb.cloud.order.model.ProductStockExample;
import com.xb.cloud.order.model.So;
import com.xb.cloud.order.model.SoExample;
import com.xb.cloud.order.model.SoExample.Criteria;
import com.xb.cloud.order.model.SoSku;
import com.xb.cloud.order.model.SoSkuExample;
import com.xb.cloud.order.model.mapper.HistorySoMapper;
import com.xb.cloud.order.model.mapper.ProductStockMapper;
import com.xb.cloud.order.model.mapper.SellOrderMapper;
import com.xb.cloud.order.model.mapper.SoMapper;
import com.xb.cloud.order.model.mapper.SoSkuMapper;
import com.xb.cloud.order.service.client.SellOrderService;
import com.xb.cloud.order.service.client.bo.OrderQueryBo;
import com.xb.cloud.order.service.client.bo.SellOrderBo;
import com.xb.cloud.order.service.client.bo.SellOrderItemBo;
import com.xb.cloud.order.service.client.bo.SellOrderOperationBo;
import com.xb.cloud.order.service.client.bo.SoDeliveryBo;
import com.xb.cloud.order.service.client.bo.SoSummaryBo;
import com.xb.cloud.service.client.ServiceReturnCodes;
import com.xb.cloud.service.client.ServiceReturnInfo;
import com.xb.cloud.service.client.ServiceReturnUtils;
import com.xb.cloud.user.service.client.ShoppingCartService;
import com.xb.cloud.user.service.client.bo.EndUserCartBo;

@Service
public class SellOrderServiceImpl extends AbstractService implements SellOrderService {
	private static final Logger LOGGER = LoggerFactory.getLogger(SellOrderServiceImpl.class);

	@Resource
	SoMapper soMapper;

	@Resource
	SoSkuMapper soSkuMapper;

	@Resource
	ProductStockMapper productStockMapper;

	@Resource
	SellOrderMapper sellOrderMapper;

	@Resource
	ShoppingCartService shoppingCartService;

	@Resource
	HistorySoMapper historySoMapper;

	@Override
	public int countUserOrderByStatus(OrderQueryBo orderQueryBo) {
		SoExample example = new SoExample();
		Criteria criteria = example.createCriteria().andCompanyIdEqualTo(orderQueryBo.getCompanyId())
				.andEndUserIdEqualTo(orderQueryBo.getEndUserId()).andIsLeafEqualTo(DbConstants.TRUE)
				.andIsUserDeletedEqualTo(DbConstants.FALSE);
		if (orderQueryBo.getStatus() != null) {
			criteria.andSoStatusEqualTo(orderQueryBo.getStatus());
		}
		return soMapper.countByExample(example);
	}

	@Override
	public List<SoSummaryBo> getUserOrderListByStatus(OrderQueryBo orderQueryBo) {
		SoExample example = new SoExample();
		example.setStartPage(orderQueryBo.getStartPage());
		example.setPageSize(orderQueryBo.getPageSize());
		// 查询用户子订单，父订单用于统计等
		Criteria criteria = example.createCriteria().andCompanyIdEqualTo(orderQueryBo.getCompanyId())
				.andEndUserIdEqualTo(orderQueryBo.getEndUserId()).andIsLeafEqualTo(DbConstants.TRUE)
				.andIsUserDeletedEqualTo(DbConstants.FALSE);
		if (orderQueryBo.getStatus() != null) {
			criteria.andSoStatusEqualTo(orderQueryBo.getStatus());
		}
		example.setOrderByClause(" create_time desc, update_time desc");
		return sellOrderMapper.selectOrderList(example);
	}

	@Override
	public Map<String, Integer> getOrderCountWithStatus(OrderQueryBo orderQueryBo) {
		SoExample example = new SoExample();
		Criteria criteria = example.createCriteria().andCompanyIdEqualTo(orderQueryBo.getCompanyId())
				.andEndUserIdEqualTo(orderQueryBo.getEndUserId()).andIsLeafEqualTo(DbConstants.TRUE)
				.andIsUserDeletedEqualTo(DbConstants.FALSE);
		if (orderQueryBo.getStatus() != null) {
			criteria.andSoStatusEqualTo(orderQueryBo.getStatus());
		}

		List<Map<String, Object>> orderCountWithStatus = soMapper.getOrderCountWithStatus(example);
		Map<String, Integer> resultMap = new HashMap<>();
		if (orderCountWithStatus != null) {
			for (Map<String, Object> map : orderCountWithStatus) {
				Long count = (Long) map.get("count");
				Integer status = (Integer) map.get("status");
				resultMap.put(String.valueOf(status), count.intValue());
			}
		}

		return resultMap;
	}

	@Override
	public SoDeliveryBo getOrderDetailsById(Long orderId) {
		return sellOrderMapper.selectOrderDetailsById(orderId);
	}

	@Override
	@Transactional(value = "transactionManager_order", propagation = Propagation.REQUIRED)
	public SellOrderBo generateOrder(List<SellOrderBo> orderList, EndUserCartBo endUserCart) {
		if (CollectionUtils.isEmpty(orderList)) {
			// TODO:
		}
		SellOrderBo firstSellOrder = orderList.get(0);
		SellOrderBo parentOrder = firstSellOrder.getParentOrder();
		if (parentOrder != null) {
			// TODO:insert parent order
		}

		for (SellOrderBo sellOrderBo : orderList) {
			sellOrderBo.setId(ipKeyGenerator.generateKey());
			Date currentTime = timeService.getDate();
			sellOrderBo.setCreateTime(currentTime);
			So sellOrder = BeanUtils.newAndCopyProperties(So.class, sellOrderBo);
			soMapper.insertSelective(sellOrder);

			List<SellOrderItemBo> items = sellOrderBo.getItems();
			for (SellOrderItemBo sellOrderItemBo : items) {
				SoSku orderSku = BeanUtils.newAndCopyProperties(SoSku.class, sellOrderItemBo);
				orderSku.setId(ipKeyGenerator.generateKey());
				orderSku.setCreateTime(currentTime);
				orderSku.setSoId(sellOrder.getId());
				soSkuMapper.insertSelective(orderSku);

				ProductStock productStock = new ProductStock();
				productStock.setCompanyId(orderSku.getCompanyId());
				productStock.setShopId(orderSku.getShopId());
				productStock.setProductId(orderSku.getProductId());
				productStock.setRealFrozenStockNum(Long.valueOf(orderSku.getSkuNum()));
				productStock.setUpdateTime(currentTime);
				int updateSkuStock = productStockMapper.updateSkuStock(productStock);//
				if (updateSkuStock <= 0) {
					// 购物车更新失败
					TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
				}
			}

			if (parentOrder == null) {
				parentOrder = sellOrderBo;
			}
		}

		int updated = shoppingCartService.updateCartValues(endUserCart);
		if (updated <= 0) {
			// 购物车更新失败
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}

		return parentOrder;
	}

	@Transactional(value = "transactionManager_order")
	@Override
	public ServiceReturnInfo cancelOrderbyEndUser(SellOrderOperationBo operationBo) throws Exception {
		SoExample example = new SoExample();
		Criteria criteria = example.createCriteria();
		criteria.andIdEqualTo(operationBo.getOrderId());
		// 10 表示未支付
		criteria.andSoStatusEqualTo(DbConstants.SO_STATUS_AWAITE_PAY);
		criteria.andIsUserDeletedEqualTo(DbConstants.FALSE);
		criteria.andEndUserIdEqualTo(operationBo.getEndUserId());
		/*
		 * if(operationBo.getEndUserId() ==0) {
		 * ServiceReturnUtils.error(ServiceReturnCodes.
		 * ORDER_OPERATION_PARAMTER_ERROR); }
		 */
		if (operationBo.getCompanyId() == 0) {
			return ServiceReturnUtils.error(ServiceReturnCodes.ORDER_OPERATION_PARAMTER_ERROR);
		}
		List<So> soList = soMapper.selectByExample(example);
		if (soList.isEmpty()) {
			return ServiceReturnUtils.error(ServiceReturnCodes.ORDER_NOT_EXIST);
		}
		Date dbTime = timeService.getDate();
		So so = soList.get(0);
		/**
		 * 逻辑如下： 1：如果是子单，1.1更新子单状态；1.2查询子单对应的sku列表；1.3更新sku的库存
		 * 2：如果是父单，1.1查询子单；1.2更新子单和父单状态；1.3 根据子单查询sku列表; 1.4更新sku库存
		 */
		switch (so.getIsLeaf()) {
		case DbConstants.PARENT_ORDER:
			// 为父单逻辑
			example.clear();
			Criteria subSoCriteria = example.createCriteria();
			subSoCriteria.andParentSoIdEqualTo(so.getId());
			List<So> subSoList = soMapper.selectByExample(example);
			// 因为父单也需要修改状态，所以加到子单列表一起更新了
			subSoList.add(so);
			updateSoStatus2Cancel(subSoList, operationBo.getEndUserId(), operationBo.getEndUserName(), dbTime);
			break;
		case DbConstants.LEAF_ORDER:
			// 子单逻辑
			updateSoStatus2Cancel(soList, operationBo.getEndUserId(), operationBo.getEndUserName(), dbTime);
			break;
		}

		// SO添加操作日志

		HistorySo historySo = buildHistorySo(so, operationBo.getEndUserId(), operationBo.getEndUserName(), dbTime);
		int insertCount = historySoMapper.insert(historySo);
		if (insertCount <= 0) {
			throw new RuntimeException();
		}
		return ServiceReturnUtils.success();
	}

	private HistorySo buildHistorySo(So so, long userId, String userName, Date dbTime) {
		HistorySo historySo = BeanUtils.newAndCopyProperties(HistorySo.class, so);
		historySo.setOperateTime(dbTime);
		historySo.setOperateUserId(userId);
		historySo.setOperateUserName(userName);
		// 更新
		historySo.setOperateType((byte) 0);
		return historySo;
	}

	private void updateSoStatus2Cancel(List<So> soList, long userId, String userName, Date dbTime) throws Exception {
		// 更新so状态
		List<ProductStock> updateSkuStockList = new ArrayList<ProductStock>();
		List<So> updateSoList = new ArrayList<So>();
		ProductStockExample productStockExample = new ProductStockExample();
		SoSkuExample example = new SoSkuExample();

		for (So so : soList) {
			So updateSo = new So();
			updateSo.setId(so.getId());
			updateSo.setSoStatus(DbConstants.SO_STATUS_ALREADY_CANCEL);
			updateSo.setVersionNo(so.getVersionNo() + 1);
			updateSo.setEndUserId(userId);
			updateSo.setUpdateTime(dbTime);
			updateSo.setCancelTime(dbTime);
			updateSoList.add(updateSo);
			if (so.getIsLeaf() == DbConstants.PARENT_ORDER) {
				continue;
			}
			// 获取子单中sku信息
			example.clear();
			com.xb.cloud.order.model.SoSkuExample.Criteria criteria = example.createCriteria();
			criteria.andSoIdEqualTo(so.getId());
			List<SoSku> soSkuList = soSkuMapper.selectByExample(example);
			for (SoSku soSku : soSkuList) {
				ProductStock productStock = new ProductStock();
				// skuStockBo.setProductId(soSku.getProductId());
				// skuStockBo.setShopId(soSku.getShopId());
				// 设置需要减的库存
				productStock.setRealFrozenStockNum(Long.valueOf(soSku.getFrozenRealStockNum()));
				productStockExample.clear();
				// 批量更新需要数据的id，所以需要更加productid和shopid到库存表中获取记录的id
				com.xb.cloud.order.model.ProductStockExample.Criteria stockCriteria = productStockExample
						.createCriteria();
				stockCriteria.andProductIdEqualTo(soSku.getProductId());
				stockCriteria.andShopIdEqualTo(soSku.getShopId());

				List<ProductStock> stockDBInfoList = productStockMapper.selectByExample(productStockExample);
				productStock.setId(stockDBInfoList.get(0).getId());
				productStock.setUpdateUserId(userId);
				productStock.setUpdateUserName(userName);
				productStock.setUpdateTime(dbTime);
				updateSkuStockList.add(productStock);
			}
		}
		int updateCount = 0;
		try {
			updateCount = soMapper.updateSoBatch(updateSoList);

		} catch (Exception e) {
			System.err.println(e);
		}
		if (soList.size() != updateCount) {
			// 如果没有全部更新成功，需要回滚
			throw new RuntimeException();
		}

		UpdateInfo info = new UpdateInfo();
		info.setUpdateTime(dbTime);
		info.setUpdateUserId(userId);
		info.setUpdateUserName(userName);
		try {
			updateCount = productStockMapper.updateStockBatch4CancelOrder(updateSkuStockList, info);

		} catch (Exception e) {
			System.err.println(e);
		}
		if (updateSkuStockList.size() != updateCount) {
			// 如果没有全部更新成功，需要回滚
			throw new RuntimeException();
		}
	}

	@Override
	public ServiceReturnInfo deleteOrderbyEndUser(SellOrderOperationBo operationBo) throws Exception {
		SoExample example = new SoExample();
		Criteria criteria = example.createCriteria();
		criteria.andIdEqualTo(operationBo.getOrderId());
		// 只有so的状态为50-已完成 和 70-已取消 才可以删除
		List<Integer> soStatus = new ArrayList<Integer>();
		soStatus.add(50);
		soStatus.add(70);
		criteria.andSoStatusIn(soStatus);
		criteria.andIsUserDeletedEqualTo((byte) 0);
		criteria.andIdEqualTo(operationBo.getOrderId());
		criteria.andEndUserIdEqualTo(operationBo.getEndUserId());
		List<So> soList = soMapper.selectByExample(example);
		if (soList.isEmpty()) {
			return ServiceReturnUtils.error(ServiceReturnCodes.ORDER_NOT_EXIST);
		}

		Date dbTime = timeService.getDate();
		So so = soList.get(0);
		/**
		 * 逻辑如下： 1：如果是子单，1.1更新子单状态；1.2查询子单对应的sku列表；1.3更新sku的库存
		 * 2：如果是父单，1.1查询子单；1.2更新子单和父单状态；1.3 根据子单查询sku列表; 1.4更新sku库存
		 */
		switch (so.getIsLeaf()) {
		case DbConstants.PARENT_ORDER:
			// 为父单逻辑
			example.clear();
			Criteria subSoCriteria = example.createCriteria();
			subSoCriteria.andParentSoIdEqualTo(so.getId());
			List<So> subSoList = soMapper.selectByExample(example);
			// 因为父单也需要修改状态，所以加到子单列表一起更新了
			subSoList.add(so);
			updateSoStatus2Delete(subSoList, operationBo.getEndUserId(), operationBo.getEndUserName(), dbTime);
			break;
		case DbConstants.LEAF_ORDER:
			// 子单逻辑
			updateSoStatus2Delete(soList, operationBo.getEndUserId(), operationBo.getEndUserName(), dbTime);
			break;
		}

		// SO添加操作日志

		HistorySo historySo = buildHistorySo(so, operationBo.getEndUserId(), operationBo.getEndUserName(), dbTime);
		int insertCount = historySoMapper.insert(historySo);
		if (insertCount <= 0) {
			throw new RuntimeException();
		}
		return ServiceReturnUtils.success();

	}

	private void updateSoStatus2Delete(List<So> soList, long userId, String userName, Date dbTime) throws Exception {
		// 更新so状态
		List<So> updateSoList = new ArrayList<So>();

		for (So so : soList) {
			So updateSo = new So();
			updateSo.setId(so.getId());
			updateSo.setVersionNo(so.getVersionNo() + 1);
			updateSo.setEndUserId(userId);
			updateSo.setUpdateTime(dbTime);
			updateSo.setIsUserDeleted((byte) 1);
			updateSoList.add(updateSo);

		}
		int updateCount = 0;
		updateCount = soMapper.updateSoBatch(updateSoList);
		if (soList.size() != updateCount) {
			// 如果没有全部更新成功，需要回滚
			throw new RuntimeException();
		}

	}

	/**
	 * 订单支付完成后更新订单信息
	 * 
	 * @param sellOrderBo
	 * @return
	 * @see com.xb.cloud.order.service.client.SellOrderService#completeOrderPayment(com.xb.cloud.order.service.client.bo.SellOrderBo)
	 */
	@Override
	public ServiceReturnInfo completeOrderPayment(SellOrderBo sellOrderBo) {
		SoExample soExample = new SoExample();
		Criteria criteria = soExample.createCriteria().andIsLeafEqualTo(DbConstants.TRUE)
				.andIsUserDeletedEqualTo(DbConstants.FALSE).andIdEqualTo(sellOrderBo.getId());

		List<So> soList = soMapper.selectByExample(soExample);
		if (soList == null || soList.size() == 0) {
			LOGGER.error("支付回调，查询订单不存在。订单id：{}", sellOrderBo.getId());
			return ServiceReturnUtils.error(ServiceReturnCodes.ORDER_NOT_EXIST);
		} else {
			So so = soList.get(0);
			if (so.getSoStatus().intValue() != DbConstants.SO_STATUS_AWAITE_PAY) {
				LOGGER.error("支付回调，查询订单状态不正确。当前订单id：{}，状态：{}", sellOrderBo.getId(), so.getSoStatus());
				return ServiceReturnUtils.error(ServiceReturnCodes.ORDER_STATUS_INVALID);
			} else {
				Date now = timeService.getDate();
				So record = new So();
				record.setSoStatus(DbConstants.SO_STATUS_ALREADY_PAY); // 已支付
				record.setPaymentType(DbConstants.ORDER_PAYMENT_TYPE_ONLINE);// 线下支付
				record.setUpdateTime(now);
				record.setPaymentConfirmTime(now);
				criteria.andSoStatusEqualTo(DbConstants.SO_STATUS_AWAITE_PAY);
				int updateRow = soMapper.updateByExampleSelective(record, soExample);
				if (updateRow > 0) {
					LOGGER.info("支付回调，查询订单存在更新成功。订单id：{}", sellOrderBo.getId());
					return ServiceReturnUtils.success();
				} else {
					LOGGER.error("支付回调，查询订单存在更新失败。订单id：{}", sellOrderBo.getId());
					return ServiceReturnUtils.error(ServiceReturnCodes.ORDER_UPDATE_FAILED); // 更新失败
				}
			}
		}
	}

}
